/*
 * DThread.h
 *
 *  Created on: 28.10.2013
 *      Author: ulgish
 */

#ifndef DTHREAD_H_
#define DTHREAD_H_

#include <pthread.h>
#include <cstdlib>
namespace DT {


using std::malloc;
using std::free;

struct PTR{
	void* THIS;
	void* ARG;
};

class DThread {
private:
	pthread_t thread;
	DThread(const DThread& orig);
	static void* thread_func(void* arg){
		DThread* THIS = (DThread*)get_this(arg);
		void* ARG = get_arg(arg);
		free_ptr(arg);
		return (THIS->run(ARG));
	};
	static void* make_ptr(void* THIS, void* ARG){
		PTR* p =(PTR*)malloc(sizeof(PTR));
		p->THIS = THIS;
		p->ARG = ARG;
		return p;
	}
	static void* get_this(void* ptr){
		return ((PTR*)ptr)->THIS;
	}
	static void* get_arg(void* ptr){
		return ((PTR*)ptr)->ARG;
	}

	static void free_ptr(void* ptr){
		if (ptr != NULL){
			std::free(ptr);
		}
	}

protected:
	virtual void* run(void* arg) = 0;
public:
	DThread();

	int start(void* arg){
		return pthread_create(&thread, NULL, DThread::thread_func, DThread::make_ptr((void*)this, arg));
	};
	int wait(void** ret){
		return pthread_join(this->thread, ret);
	};
	virtual ~DThread();
};

}

#endif /* DTHREAD_H_ */
